import statistics
from typing import Union
from decimal import Decimal, ROUND_DOWN


def calculate_cpk(array: list, length: int = 2) -> Union[int, float, None]:
    """
    CPK 统计, 第一个需要做cpk 数组，
    :param array:
    :param length:
    :return:
    """
    resp_cpk: Union[int, float, None] = None
    if not isinstance(array, list) or len(array) < length:
        # return None
        return 0

    # noinspection PyBroadException
    try:
        total: Decimal = Decimal(0)
        lsl: Decimal = Decimal(min(array)).quantize(Decimal("0.000000"), ROUND_DOWN)
        usl: Decimal = Decimal(max(array)).quantize(Decimal("0.000000"), ROUND_DOWN)
        t: Decimal = Decimal(usl - lsl).quantize(Decimal("0.000000"), ROUND_DOWN)

        mean_value: Decimal = Decimal(statistics.mean(array)).quantize(Decimal("0.000000"), ROUND_DOWN)
        center: Decimal = Decimal(statistics.median(array)).quantize(Decimal("0.000000"), ROUND_DOWN)

        for index, itr in enumerate(array):
            total = total + (Decimal(itr) - mean_value) ** 2
        total: Decimal = Decimal(total).quantize(Decimal("0.000000"), ROUND_DOWN)

        deviation: Decimal = (total / Decimal((len(array)))).sqrt()
        cp: Decimal = (usl - lsl) / (Decimal(6) * deviation)
        ca: Decimal = (mean_value - center) / (t / Decimal(2))

        cpk: Decimal = cp * (Decimal(1) - ca)
        resp_cpk: float = Decimal(cpk).quantize(Decimal("0.0000"), ROUND_DOWN).__float__()
    except Exception as e:
        # resp_cpk = None
        resp_cpk = 0

    return resp_cpk
